import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;



public class CipherTextAttack {
protected PlainReader m_pReader;
	public CipherTextAttack(int BlockSize,FileReader fileReader) throws IOException {
		m_pReader = new PlainReader(BlockSize, fileReader);
	}
	public String [] CheckFromPossibleKeys(char [] iv)
	{
		String [] pos = new String [8];
		for(int i = 0;i<pos.length;i++)
		{
			pos[i]="";
		}
		char [] block = new char[m_pReader.m_iBlockSize]; //10
		while (m_pReader.GetNextBlock(block))
		{
			for (int i = 0;i < block.length;i++)
			{
				if (IsInterestingChar(block[i]))
				{
					pos[CastCharToAraayPlace(block[i])]+=iv[i];
				}
			}
			iv = block.clone();
		}
		return pos;
	}
	public void CheckCombinations (String [] pos,String file) throws IOException
	{
		String [] Dictionary = new String [pos.length];
		for(int i = 0;i<Dictionary.length;i++)
		{
			Dictionary[i]="";
		}
		for (int i = 0; i < pos.length;i++)
		{
			for (int c = 97;c <=104;c++)
			{
				boolean row = true;
				for (int j = 0;j<pos[i].length();j++)
				{
 					if (!(CheackLigleChar((char) ((char)c^pos[i].charAt(j)))))
					{
						row = false;
						break;
					}
				}
				if (row)
				{
					Dictionary[i]+=(char)c;
				}
			}
		}
		for (int i = 0;i<Dictionary.length;i++)
		{
			if (Dictionary[i].length() > 1)
			{
				for (int j = 0;j < Dictionary[i].length();j++)
				{
					for (int v = 0;((v<Dictionary.length));v++)
					{
						if (v != i){
							if (Dictionary[v].length() == 1)
							{
								if (Dictionary[v].charAt(0) == (Dictionary[i].charAt(j)))
								{
									String news = "";
									for (int s = 0;s<Dictionary[i].length();s++)
									{
										if (Dictionary[i].charAt(s)!=Dictionary[i].charAt(j))
										{
											news+=Dictionary[i].charAt(s);
										}
									}
									Dictionary[i] = news;
									break;
								}
							}
						}
					}
				}
			}
		}
		for (int i=0;i<Dictionary.length;i++)
		{
			if (Dictionary.length > 1)
			{
				for (int j = 0;j < Dictionary.length;j++)
				{
					if (i!=j)
					{
						if (Dictionary[i].equals(Dictionary[j]))
						{
							Dictionary[i] ="" + Dictionary[i].charAt(0);
							Dictionary[j] ="" + Dictionary[j].charAt(1);
						}
					}
				}
			}
		}
		String name = file.substring(0,file.length()-7);
		FileWriter outFile = new FileWriter(name + "_key.txt");
		PrintWriter out = new PrintWriter(outFile);
		for (int i = 0;i < Dictionary.length;i++)
		{
			out.println(Dictionary[i] + "  " + (char)(i + 97));
		}
		out.close();
	}
	private int CastCharToAraayPlace (char c)
	{
		return (int)c - 97; 
	}
	private boolean IsInterestingChar (char c)
	{
		int ic = c;
		return ((ic >=97)&&(ic<=104));
	}
	// return true if the char is in the possible range
	protected boolean CheackLigleChar(char c)
	{
		int [][] arr = {{0,2},{4,9},{11,11},{12,12},{14,31},{127,127}};
		int ic = c;
		//if ((int)c > 127) return false;
		for (int i = 0;i<arr.length;i++){
			if ((ic >=arr[i][0])&&(ic <=arr[i][1])){

				return false;
				
			}
		}
		return true;
	}
	public String [] ConvertKeys(String keyspath) throws IOException
	{
		String [] keys = new String[8];
		BufferedReader br = new BufferedReader(new FileReader(keyspath));
		String line = br.readLine();
        while (line != null) {
            char makor = line.charAt(0);
            line=line.substring(1);
            line=line.trim();
            keys[(int)makor - 97] = "" + line.charAt(0);
            line = br.readLine();
        }
        return keys;
	}
	public void Encryption (String ptextPath,char[] iv,String [] Dictionary) throws IOException
	{
		FileWriter outFile = new FileWriter(ptextPath.substring(0,ptextPath.length()-3)+"CIPHER");
		PrintWriter out = new PrintWriter(outFile);
		PlainReader m_pReader = new PlainReader(10,new FileReader(ptextPath));
		char [] block = new char[10];
		while (m_pReader.GetNextBlock(block))
		{
			for (int i = 0;i < block.length;i++)
			{
				block[i] = (char) (block[i]^iv[i]);
				if (IsInterestingChar(block[i]))
				{
					block[i] = Dictionary[(int)(block[i] - 97)].charAt(0);
				}
			}
			out.print(block);
			iv = block.clone();
		}
		out.close();
	}
	public static void main(String[] args) throws IOException {
		CipherTextAttack c = new CipherTextAttack(10,new FileReader(args[1]));
		if (args[0].equals("DecryptionA"))
		{
			PlainReader p = new PlainReader(10,new FileReader(args[2]));
			char [] b = new char[10];
			p.GetNextBlock(b);
			String [] pos = c.CheckFromPossibleKeys(b);
			c.CheckCombinations(pos,args[1]);
		}
		else if (args[0].equals("EncryptionA"))
		{
			PlainReader p = new PlainReader(10,new FileReader(args[3]));
			char [] iv = new char[10];
			p.GetNextBlock(iv);
			c.Encryption(args[1], iv, c.ConvertKeys(args[2]));
		}

	}

}
